﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace CommonUtils
{
    public static class MapUtil
    {
        public static void TryToRemove<TKey, TValue>(this Dictionary<TKey, TValue> map, TKey key)
        {
            if (map.ContainsKey(key))
                map.Remove(key);
        }

        /// <summary>
        /// 删除空
        /// </summary>
        public static void RemoveEmpty(this Dictionary<string, string> map)
        => map.RemoveValue("", null);

        /// <summary>
        /// 判空取值
        /// </summary>
        public static TValue Get<TKey, TValue>(this Dictionary<TKey, TValue> map, TKey key, TValue defaultValue = default, bool log = false)
        {
            if (key != null && map.ContainsKey(key))
                return map[key];
            if (log)
                LogUtil.Write(string.Format("Dictionary尝试获取不存在的Key：{0}\r\n{1}", key, new StackTrace(true).Take(5)));
            return defaultValue;
        }

        /// <summary>
        /// 按值取键
        /// </summary>
        public static TKey GetKeyByValue<TKey, TValue>(this Dictionary<TKey, TValue> map, TValue value)
        {
            foreach (var pair in map)
                if (pair.Value.Equals(value))
                    return pair.Key;
            return default;
        }

        /// <summary>
        /// 赋值,默认覆盖，可选保留
        /// </summary>
        public static void Set<TKey, TValue>(this Dictionary<TKey, TValue> map, TKey key, TValue value, bool replace = true)
        {
            if (key == null)
                return;

            if (!replace && map.ContainsKey(key))
                return;

            map[key] = value;
        }

        /// <summary>
        /// 填值
        /// </summary>
        public static void Add<TKey, TValue>(this Dictionary<TKey, TValue> map, Dictionary<TKey, TValue> otherMap)
        {
            foreach (var item in otherMap)
                map.Add(item.Key, item.Value);
        }

        /// <summary>
        /// 根据Value删除项
        /// </summary>
        public static void RemoveValue<TKey, TValue>(this Dictionary<TKey, TValue> map, params TValue[] values)
        {
            List<TKey> keys = new List<TKey>();
            foreach (var value in values)
            {
                if (map.ContainsValue(value))
                {
                    foreach (var pair in map)
                    {
                        if (pair.Value.Equals(value))
                            keys.Add(pair.Key);
                    }
                }
            }
            foreach (TKey key in keys)
                map.Remove(key);
        }

        /// <summary>
        /// 根据Keys删除项
        /// </summary>
        public static void Remove<TKey, TValue>(this Dictionary<TKey, TValue> map, TKey[] keys)
        {
            foreach (var key in keys)
                map.Remove(key);
        }

        ///// <summary>
        ///// 根据Keys筛选项
        ///// </summary>
        //public static void Select<TKey, TValue>(this Dictionary<TKey, TValue> map, TKey[] keys)
        //{
        //    var allKeys = map.Keys.ToArray();
        //    foreach (var key in allKeys)
        //        if (!keys.Contains(key))
        //            map.Remove(key);
        //}

        /// <summary>
        /// 排序
        /// </summary>
        public static Dictionary<TKey, TValue> GetNewSortByKey<TKey, TValue>(this Dictionary<TKey, TValue> map)
        => map.OrderBy(m => m.Key).ToDictionary(m => m.Key, m => m.Value);

        /// <summary>
        /// 排序
        /// </sum
        public static void SortByKey<TKey, TValue>(this Dictionary<TKey, TValue> map)
        {
            var sortedMap = map.GetNewSortByKey();
            map.Clear();
            foreach (var keyValue in sortedMap)
                map.Add(keyValue.Key, keyValue.Value);
        }

        #region Hashtable 无序Map
        public static void Add(this Hashtable hashtable, Hashtable keysValues)
        {
            foreach (var key in keysValues.Keys)
                hashtable.Add(key, hashtable[key]);
        }

        public static object Get(this Hashtable hashtable, object key, bool log = true)
        {
            if (hashtable.Contains(key))
                return hashtable[key];
            if (log)
                LogUtil.WriteWithStackTrace("HashtableException 尝试获取不存在的Key:" + key);
            return null;
        }

        public static Pair<object, object>[] KeyValuePairs(this Hashtable hashtable)
        {
            var pairs = new List<Pair<object, object>>();
            foreach (var key in hashtable.Keys)
                pairs.Add(new Pair<object, object>(key, hashtable[key]));
            return pairs.ToArray();
        }

        public static StringStringMap ToMap(this Hashtable hashtable)
        {
            var map = new StringStringMap();
            foreach (var key in hashtable.Keys)
                map.Add(key.ToString(), hashtable[key].ToString());
            return map;
        }

        public static StringStringMap Sort(this Hashtable hashtable)
        {
            var keys = new List<string>();
            foreach (var key in hashtable.Keys)
                keys.Add(key.ToString());
            keys = keys.OrderBy(m => m).ToList();
            StringStringMap map = new StringStringMap();
            foreach (var key in keys)
                map.Add(key, hashtable[key].ToString());
            return map;
        }
        #endregion
    }
}
